/**
 * 请求拦截器
 * 
 * 功能说明：
 * 1. 统一处理请求头和请求参数
 * 2. 拦截401错误码，自动处理Token失效情况
 * 3. 当接收到以下响应时，会自动跳转到登录页面：
 *    - code: 401
 *    - message: "Token失效，请重新登录!"
 *    - success: false
 * 4. 统一错误处理和成功响应处理
 */

import { request, hideLoading } from '@tarojs/taro';
// import { REQUEST_TIMEOUT, SUCCESS_CODE, REFRESH_TOKEN_CODE, UNAUTHORIZED_CODE } from '@/constants';
import { getRequestUrl, getRequestHeaders, handleExpireToken, showErrorMsg } from './helpers';

async function axios<T>(config: Service.RequestParam): Promise<Service.RequestResult<T>> {
  const { method, url, data } = config;
  const axiosConfig = config.axiosConfig as Service.AxiosConfig;
  const header = getRequestHeaders(axiosConfig);
  return await new Promise((resolve, reject) => {
    request({
      /** 兼容Url不同的情况，可以通过填写完整路径 */
      url: getRequestUrl(url),
      method,
      /** 对所有请求添加时间戳以防止缓存 */
      data: { _t: Date.now(), ...data },
      header,
      timeout: 5000,
      success: res => {

        const data = res.data as Service.BackendResultConfig<T>;

        const { code, message, result } = data
        /* 成功请求 */
        if (code === 200 || (code === 0 && data?.result)) {

          return resolve({
            error: null,
            success: result === null || result === undefined ? (data as any) : result
          });

        }

        // 处理401错误 - Token失效，需要重新登录
        if (code == 401) {
          console.log('检测到401错误，Token失效，准备跳转登录页面');
          handleExpireToken();
          return resolve({
            error: {
              message: message || 'Token失效，请重新登录!',
              errorCode: code
            },
            success: null
          });
        }

        const msg = ['退出登录失败！', 'Token失效，请重新登录!']
        // 兜底处理：如果是刷新token的错误码且消息匹配
        if ('401'.includes(code) && message === 'Token失效，请重新登录!') {
          console.log('通过消息匹配检测到Token失效');
          handleExpireToken();
          return resolve({
            error: {
              message,
              errorCode: code
            },
            success: null
          });
        }
        
        /** 仅有使用服务端错误信息的请求才 toast 提示错误 */
        if (axiosConfig.useErrMsg && msg.indexOf(message) < 0) {
          showErrorMsg(message)
        }
        return resolve({
          error: {
            message,
            errorCode: code
          },
          success: null
        });
      },
      fail: err => {
        reject(err);
        hideLoading()
      },
      complete: () => {
      }
    });
  });
}

export default axios;
